package com.lin.blog.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lin.blog.constant.UserConstant;
import com.lin.blog.entity.Permission;
import com.lin.blog.entity.Role;
import com.lin.blog.entity.User;
import com.lin.blog.entity.UserRole;
import com.lin.blog.mapper.PermissionMapper;
import com.lin.blog.mapper.UserMapper;
import com.lin.blog.mapper.UserRoleMapper;
import com.lin.blog.service.IPermissionService;
import com.lin.blog.service.IRoleService;
import com.lin.blog.service.IUserService;
import com.lin.constant.RedisConstant;
import com.lin.constant.ResultCode;
import com.lin.shiro.utils.JwtUtil;
import com.lin.shiro.utils.SHA256Util;
import com.lin.utils.RedisUtils;
import com.lin.utils.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author lin
 * @since 2020-03-08
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private IRoleService roleService;

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Autowired
    private IPermissionService permissionService;


    /**
     * 后台登出
     *
     * @param token
     * @return
     */
    @Override
    public Result adminLogout(String token) {
        // 0. 判断token是否有效
        if (StringUtils.isEmpty(token)) {
            return Result.failure(ResultCode.PARAM_IS_BLANK);
        }

        // 1. 获取username
        JwtUtil jwtUtil = new JwtUtil();
        String username = (String) jwtUtil.decode(token).get("username");

        // 删除缓存
        Long count = RedisUtils.batchDelPre(username);

        if (count > 0) {
            return Result.success();
        }
        return Result.failure(ResultCode.FAIL);
    }

    /**
     * 后台登录 通过token获取用户信息
     *
     * @param token
     * @return
     */
    @Override
    public Result getUserInfoByToken(String token) {

        Map<String, Object> userInfo = new HashMap<>(16);


        // 0. 判断token是否有效
        if (StringUtils.isEmpty(token)) {
            return Result.failure(ResultCode.PARAM_IS_BLANK);
        }

        // 1. 获取username
        JwtUtil jwtUtil = new JwtUtil();
        String username = (String) jwtUtil.decode(token).get("username");

        // 1.1 从缓存中获取
        String userInfoJson = (String) RedisUtils.get(username + RedisConstant.USER_INFO_SUFFIX);
        if (!StringUtils.isEmpty(userInfoJson)) {
            userInfo = JSON.parseObject(userInfoJson, Map.class);
        }
        // 1.2 缓存中无值
        if (userInfo.size() == 0) {

            // 2.获取角色
            List<Role> roles = roleService.getRoleByUserName(username);

            List<Permission> permissions = permissionService.getPermissionByRoleName(roles.get(0).getName());

            User user = userMapper.getUserInfoByUserName(username);

            // 3.使用Map封装结果
            userInfo.put("userName", username);
            userInfo.put("roles", roles);
            userInfo.put("permissions", permissions);
            userInfo.put("user", user);

            RedisUtils.set(username + RedisConstant.USER_INFO_SUFFIX, JSON.toJSONString(userInfo), RedisConstant.USER_INFO_PRE_EXPIRE);
        }
        return Result.success(userInfo);
    }

    /**
     * 设置昵称
     *
     * @param userId
     * @param nickName
     * @return
     */
    @Override
    public Result setNickName(Long userId, String nickName) {
        // 参数无效
        if (StringUtils.isEmpty(userId)
                || StringUtils.isEmpty(nickName)) {
            return Result.failure(ResultCode.PARAM_IS_BLANK);
        }

        User user = new User();
        user.setId(userId);

        // 设置昵称
        user.setNickname(nickName);

        // 更新
        if (userMapper.updateById(user) > 0) {
            return Result.success();
        }
        return Result.failure(ResultCode.UPDATE_ERROR);
    }

    /**
     * 通过ID 修改密码
     *
     * @param username
     * @param oldPassword
     * @param newPassword
     * @return
     */
    @Override
    public Result updateUserPasswordByUserName(String username, String oldPassword, String newPassword) {
        // 参数无效
        if (StringUtils.isEmpty(username)
                || StringUtils.isEmpty(oldPassword)
                || StringUtils.isEmpty(newPassword)) {
            return Result.failure(ResultCode.PARAM_IS_BLANK);
        }
        // 旧密码加密
        String oldPasswordEncrypt = SHA256Util.sha256(oldPassword, username);

        // 查询用户时候存在
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq(UserConstant.USER_NAME, username);
        userQueryWrapper.eq(UserConstant.PASSWORD, oldPasswordEncrypt);
        int count = userMapper.selectCount(userQueryWrapper);

        if (0 != count) {
            // 新密码加密
            String newPasswordEncrypt = SHA256Util.sha256(newPassword, username);
            // 更新到数据库
            if (userMapper.updateUserPasswordByUserName(username, newPasswordEncrypt) > 0) {
                RedisUtils.del(username + RedisConstant.USER_INFO_SUFFIX);
                return Result.success();
            } else {
                return Result.failure(ResultCode.UPDATE_ERROR);
            }
        }
        return Result.failure(ResultCode.USER_USERNAME_OR_PASSWORD_ERROR);
    }

    /**
     * 更新头像
     *
     * @param username
     * @param headImageUrl
     * @return
     */
    @Override
    public Result updateUserHeadImage(String username, String headImageUrl) {
        if (userMapper.updateUserHeadImageByUserName(username, headImageUrl) > 0) {
            RedisUtils.del(username + RedisConstant.USER_INFO_SUFFIX);
            return Result.success();
        }
        return Result.failure(ResultCode.UPDATE_ERROR);
    }

    /**
     * 通过账号密码获取用户
     *
     * @param userName
     * @param password
     * @return
     */
    @Override
    public Result getUserByUserNameAndPassword(String userName, String password) {
        // 参数无效
        if (StringUtils.isEmpty(userName)
                || StringUtils.isEmpty(password)) {
            return Result.failure(ResultCode.PARAM_IS_INVALID);
        }
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", userName);
        queryWrapper.eq("password", password);
        User user = userMapper.selectOne(queryWrapper);
        if (user == null) {
            return Result.failure(ResultCode.USER_USERNAME_OR_PASSWORD_ERROR);
        }
        return Result.success(user);
    }

    /**
     * 通过主键ID查询User
     *
     * @param id
     * @return
     */
    @Override
    public Result<User> getUser(Long id) {

        // 参数不为空
        if (id == null) {
            return Result.failure(ResultCode.PARAM_IS_BLANK);
        }

        // 查询
        User user = userMapper.selectById(id);

        // 不存在
        if (user == null) {
            return Result.failure(ResultCode.USER_NOT_EXIT);
        }

        return Result.success(user);
    }

    /**
     * 添加一个用户
     *
     * @param user
     * @return
     */
    @Override
    public Result saveUser(User user) {

        // 检查用户信息 已使用validation 在bean中注解匹配 并全部返回错误信息

        // 查找是否有重复用户名
        if (checkRepeatUserName(user)) {
            return Result.failure(ResultCode.USER_HAS_EXITED);
        }

        // 密码加密
        String newPassword = SHA256Util.sha256(user.getPassword(), user.getUsername());

        user.setPassword(newPassword);

        Long id = IdWorker.getId();
        //生成唯一ID
        user.setId(id);
        //设置时间
        user.setCreateTime(LocalDateTime.now());
        //设置时间
        user.setLastTime(LocalDateTime.now());
        //设置默认头像
        user.setHeadImage(UserConstant.Default_HeadImage);
        //添加成功
        if (userMapper.insert(user) == 1) {

            // 添加User-Role 用户角色映射
            UserRole userRole = new UserRole();
            userRole.setUserId(user.getId());
            userRole.setRoleId(UserConstant.ROLE_USER_ID);
            userRoleMapper.insert(userRole);

            return Result.success(user.getId());
        }
        return Result.failure(ResultCode.INSERT_ERROR);
    }


    /**
     * 通过主键ID删除User
     *
     * @param id
     * @return
     */
    @Override
    public Result removeUser(Long id) {
        // 参数不为空
        if (id == null) {
            return Result.failure(ResultCode.PARAM_IS_BLANK);
        }
        if (userMapper.deleteById(id) > 0) {
            // 删除userRole中的数据
            userRoleMapper.deleteUserRoleByUserId(id);
            return Result.success();
        }
        return Result.failure(ResultCode.DELETE_ERROR);
    }


    /**
     * 通过主键ID更新User
     *
     * @param id
     * @param user
     * @return
     */
    @Override
    public Result updateUser(Long id, User user) {
        // 参数不为空
        if (id == null) {
            return Result.failure(ResultCode.PARAM_IS_BLANK);
        }
        // 获取用户名
        String username = user.getUsername();

        user.setId(id);
        user.setUsername(null);
        if (userMapper.updateById(user) > 0) {
            RedisUtils.del(username + RedisConstant.USER_INFO_SUFFIX);
            return Result.success();
        }
        return Result.failure(ResultCode.UPDATE_ERROR);
    }


    /**
     * 获取UserList
     *
     * @return
     */
    @Override
    public Result listUser() {
        return Result.success(userMapper.selectList(null));
    }


    /**
     * 分页获取UserList
     *
     * @return
     */
    @Override
    public Result listUser(Long pageNum, Long pageSize) {
        Page page = new Page(pageNum, pageSize);
        return Result.success(userMapper.selectPage(page, null));
    }


    /**
     * 查找是否有重复用户名
     *
     * @param user
     * @return
     */
    private boolean checkRepeatUserName(User user) {
        String username = user.getUsername();
        QueryWrapper<User> queryWrapper = new QueryWrapper();
        queryWrapper.eq("username", username);
        Integer count = userMapper.selectCount(queryWrapper);
        if (count != 0) {
            return true;
        }
        return false;
    }

}
